home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Grab Bag
/
Shareware Grab Bag.iso
/
007
/
printf.pqs
/
printf.pas
Wrap
Pascal/Delphi Source File
|
1985-08-30
|
6KB
|
195 lines
Program PRINTF;
{
By : Darrell Flenniken 70015,143 20 August 85
PRINTF is a program that implements a formatted print routine
in the style of that in the 'C' language.
The heart of this routine is a 'hack' to allow a variable
number of arguments and argument types to be passed to a
Pascal Procedure via a 'string of pointers'.
Use:
Printf(Device,Control String,_(arg1)+...+_(argn));
Where :
1.) Device is Con or Lst
2.) Control String
The Control String contains literal constants and/or print
formatting control sequences. Print format control sequences
are Escaped with a leading '%' and have the following form:
%W:Dd ....... decimal format
%W:i ....... integer format
%W:s ....... string format
%W:u ....... unsigned integer format
%W:h ....... hexidecimal (hhhh) format
%W:b ....... binary format
%t ....... next tab(8) field
%n ....... cr/lf pair
%% ....... allow printing of %
W = the total field width for argument
D = decimal precision (reals only)
W is optional for all types
:D is required for reals
a '-' following will force left justification in
field, right justification is the default.
3.) _(arg)
The '_' function returns a string containing the binary
address of the arg. Multiple args are concatenated.
The '_' was chosen as the function name to keep it short
and avoid collisions with other identifiers.
NOTES:
1.) Very little error checking is performed by these routines.
Failure to use proper syntax often leads to hung system.
2.) MS-DOS Specific, appropriate changes for CP/M can be made
in '_' and 'GetArg' for 2 Byte Pointers.
Enjoy....
}
TYPE
String4 = String[4];
String80 = String[80];
Function _(VAR Item):String4;
{ Return the Address of Item as a String }
BEGIN
_ := Chr(Lo(Seg(Item)))+Chr(Hi(Seg(Item)))+
Chr(Lo(Ofs(Item)))+Chr(Hi(Ofs(Item)))
END;
Procedure PrintF(VAR Dev:Text;Format,ArgVec:String80);
{ Print N Items pointed to in ArgVec using Format on Dev [ Con,Lst ] }
CONST
Hex : Array[0..15] OF Char = '0123456789ABCDEF';
TYPE
VecPtr = ^VecItem;
VecItem = RECORD
CASE Integer OF
1 : (I:Integer);
2 : (R:Real);
3 : (S:String80);
END;
VAR
Fws,Dps : String[6];
Fw,Dp,X,E : Integer;
TOut,LineOut : String[255];
Left : Boolean;
Arg : VecPtr;
Function GetArg:VecPtr;
{ Return a Pointer from ArgVec }
BEGIN
GetArg := Ptr((Ord(ArgVec[2]) Shl 8) + Ord(ArgVec[1]),
(Ord(ArgVec[4]) Shl 8) + Ord(ArgVec[3]));
Delete(ArgVec,1,4);
END { GetArg };
Function SStr(Num:Integer;Ch:Char):String80;
{ Return a String of length=Num composed of Char }
VAR
Temp : String80;
BEGIN
IF Num <= 0 THEN SStr := '' ELSE BEGIN
FillChar(Temp[1],Num,Ch);
Temp[0] := Chr(Num);
SStr := Temp;
END;
END { SStr };
BEGIN { PrintF }
X := 1;
LineOut := '';
WHILE X < Length(Format) DO BEGIN
Fws := '0';
Dps := '0';
WHILE (Format[X] <> '%') AND (X < Length(Format)) DO BEGIN
LineOut := LineOut+Format[X];
X := Succ(X);
END;
IF Format[X] = '%' THEN BEGIN
X := Succ(X);
IF Format[X] = '-' THEN BEGIN
Left := TRUE;
X := Succ(X);
END ELSE
Left := FALSE;
WHILE Format[X] IN ['0'..'9'] DO BEGIN
Fws := Fws+Format[X];
X := Succ(X);
END;
Val(Fws,Fw,E);
IF Format[X] = ':' THEN BEGIN
X := Succ(X);
WHILE Format[X] IN ['0'..'9'] DO BEGIN
Dps := Dps+Format[X];
X := Succ(X);
END;
END;
Val(Dps,Dp,E);
IF NOT (Format[X] IN ['%','t','n']) THEN
Arg := GetArg;
TOut := '';
CASE Format[X] OF
's' : TOut := Arg^.S; { String }
'i' : Str(Arg^.I,TOut); { Signed Integer }
'd' : Str(Arg^.R:0:DP,TOut); { Decimal }
'n' : TOut := #13+#10; { CR/LF }
't' : TOut := SStr(8-(Length(LineOut) mod 8),' '); { Tab }
'h' : TOut := Hex[Hi(Arg^.I) Shr 4]+ { Hex }
Hex[Hi(Arg^.I) AND $F]+
Hex[Lo(Arg^.I) Shr 4]+
Hex[Lo(Arg^.I) AND $F];
'b' : FOR E := 15 DOWNTO 0 DO { Binary }
TOut := TOut+Chr(((Arg^.I Shr E) AND 1)+$30);
'u' : IF Arg^.I < 0 THEN { Unsigned Integer }
Str(Arg^.I+65536.0:0:0,TOut)
ELSE
Str(Arg^.I,TOut);
'%' : TOut := '%'; { % sign }
END { CASE };
IF Left THEN
LineOut := LineOut+TOut+SStr(Fw-Length(TOut),' ')
ELSE
LineOut := LineOut+SStr(Fw-Length(TOut),' ')+TOut;
X := Succ(X);
END { IF Format[X] = '%' };
END { WHILE X < LengthFormat) };
Write(Dev,LineOut);
END { PrintF };
{ Examples of Use }
VAR
x,x2,x3,x4 : integer;
y : real;
z,Fstr : string[80];
BEGIN
x := 32767;
x2 := 3;
x3 := 345;
x4 := -999;
y := -999.456;
z := 'sam i am';
Fstr := 'test %% %20s %-12i %-:2d %h %b%n';
PrintF(Con,'test %20s %-12i %-12:2d %h %b%n',_(z)+_(x)+_(y)+_(x)+_(x));
PrintF(Con,'test %-20s %12u %12:2d %h %b%n',_(z)+_(x)+_(y)+_(x)+_(x));
PrintF(Con,FStr,_(z)+_(x)+_(y)+_(x)+_(x));
PrintF(Con,'%i%t%i%t%i%t%i',_(x)+_(x2)+_(x3)+_(x4));
PrintF(Lst,'test %20s %-12i %-12:2d %h %b%n',_(z)+_(x)+_(y)+_(x)+_(x));
PrintF(Lst,'test %-20s %12i %12:2d %h %b%n',_(z)+_(x)+_(y)+_(x)+_(x));
END.